
#include <cstdio>
#include <BPicker>
#include <BReadWrite>
#include <BPainter>
#include <BNode>
#include <BLight>
#include <BMesh>
#include <BGeometry>
#include <BSphereHandler>
#include <BBillboard>

#include <BVBoxLayout>
#include <BHBoxLayout>
#include <BGridLayout>
#include <BLabel>
#include <BStyle>

#include "ConvertDialog.h"

BTerrain* ConvertDialog::CreateTerrain(const BString& fileName)
{
	if (fileName.endWith(".tiff") || fileName.endWith(".tif"))
	{
		BImage* elevationImage = ReadFile<BImage>(fileName);
		if (!elevationImage)
		{
			perror("error : read elevation tif file faild.");
			return 0;
		}

		Format format = elevationImage->format();
		int width = elevationImage->width();
		int height = elevationImage->height();
		int size = width * height;

		BTerrain* terrain = new BTerrain(width * 100.0f, height * 100.0f, width, height);

		BRealTable& elevation = terrain->elevation();
		const BByteArray* pixels = elevationImage->pixels();
		if (format == Format_UChar)
		{
			elevation.fill((unsigned char*)pixels->data(), pixels->size());
		}
		if (format == Format_UShort)
		{
			elevation.fill((unsigned short*)pixels->data(), pixels->size() / 2);
		}
		if (format == Format_Short)
		{
			elevation.fill((short*)pixels->data(), pixels->size() / 2);
		}
		if (format == Format_UInt)
		{
			elevation.fill((unsigned int*)pixels->data(), pixels->size() / 4);
		}
		if (format == Format_Int)
		{
			elevation.fill((int*)pixels->data(), pixels->size() / 4);
		}
		if (format == Format_Float)
		{
			elevation.fill((float*)pixels->data(), pixels->size() / 4);
		}
		if (format == Format_Double)
		{
			elevation.fill((double*)pixels->data(), pixels->size() / 8);
		}
		elevation.reverse(Orientation_Vertical);
		terrain->setElevation(elevation);
		//terrain->setColor(128, 128, 128);
		terrain->smooth();

		BString textureFileName = fileName;
		textureFileName -= ".tiff";
		textureFileName -= ".tif";
		textureFileName += ".jpg";
		BImage* image = ReadFile<BImage>(textureFileName);
		if (image)
		{
			image->setBlend(BTexture::Blend_Modulate);
			terrain->setTexture(image);
		}

		return terrain;
	}
	if (fileName.endWith(".grd"))
	{
		BFile file(fileName);
		if (!file.open(IO_Read))
		{
			return 0;
		}

		BString text;
		file.readLine(text);
		text.trimmed();
		if (text != "DSAA")
			return 0;

		file.readLine(text);
		text.trimmed();
		int split = text.find(' ');
		BString pixelWidthText = text.substr(0, split);
		BString pixelHeightText = text.substr(split + 1);

		file.readLine(text);
		text.trimmed();
		split = text.find(' ');
		float minx = text.substr(0, split).toFloat();
		float maxx = text.substr(split).toFloat();

		file.readLine(text);
		text.trimmed();
		split = text.find(' ');
		float miny = text.substr(0, split).toFloat();
		float maxy = text.substr(split).toFloat();

		file.readLine(text);
		text.trimmed();
		split = text.find(' ');
		float minz = text.substr(0, split).toFloat();
		float maxz = text.substr(split).toFloat();

		int pixelWidth = pixelWidthText.toInt();
		int pixelHeight = pixelHeightText.toInt();
		float width = pixelWidth * 10.0f;
		float height = pixelHeight * 10.0f;

		BTerrain* terrain = new BTerrain(width, height, pixelWidth, pixelHeight);
		terrain->setAlign(Align_Center);
		terrain->setColor(128, 128, 128);
		terrain->flush();

		BRealTable& elevation = terrain->elevation();
		for (int r = 0; r < pixelHeight; r++)
		{
			file.readLine(text);
			text.trimmed();
			BString word;
			int head = r * pixelWidth;
			int pos = 0;
			for (int c = 0; c < pixelWidth; c++)
			{
				pos = text.word(word, pos);
				BReal z = word.toReal();
				if (z < 0)
					z = 0;
				elevation[r][c] = z;
			}
		}
		terrain->setElevation(elevation);

		BString textureFileName = fileName;
		textureFileName -= ".grd";
		textureFileName += ".jpg";
		if (!BFile::Exist(textureFileName))
		{
			textureFileName -= ".jpg";
			textureFileName += ".tiff";
		}
		BImage* image = ReadFile<BImage>(textureFileName);
		if (image)
		{
			BByte max = 0;
			BByteArray* pixels = image->pixels();
			int size = pixels->size();
			BByte* bytes = image->pixels()->data();
			if (image->format() == Format_RGB)
			{
				for (int i = 0; i < size; i++)
				{
					if (max < bytes[i])
						max = bytes[i];
				}
				float ratio = 1 + (255 - max) / 255.0f;
				for (int i = 0; i < size; i++)
				{
					bytes[i] = BByte(bytes[i] * ratio);
				}
			}
			terrain->setTexture(image);
		}

		return terrain;
	}
	return 0;
}

ConvertDialog::ConvertDialog(BWidget* parent) : BDialog(parent)
{
	this->setTitle("Terrain");
	this->setSize(1000, 660);
	this->addTitleButton(Button_Normalize);
	this->addTitleButton(Button_Minimize);

	_orthoImage = new BImage(Format_RGBA);
	_elevationImage = new BImage(Format_Gray);

	createScene();

	_viewer = new BViewer();
	_viewer->setName("convert");
	_viewer->setStyleSheet("background:gray;");
	{
		_handler = new ConvertHandler();

		_camera = new BCamera();
		_camera->setPosition(0, -2, 2);
		_camera->setCenter(0, 0, 0);
		_camera->setUp(0, 0, 1);

		_viewer->setHandler(_handler);
		_viewer->setCamera(_camera);
		_viewer->setScene(_scene);
	}

	BVBoxLayout* rightLayout = new BVBoxLayout();
	rightLayout->setMargin(2);
	rightLayout->setSpacing(2);
	rightLayout->setSizePolicy(Policy_Preferred, Policy_Expanding);
	{
		BLabel* imageLabel = new BLabel("image");
		imageLabel->setAlign(Align_Center);
		_imageSpacer = new BSpacer(192, 120, Policy_Fixed, Policy_Fixed);

		BLabel* elevationLabel = new BLabel("elevation");
		elevationLabel->setAlign(Align_Center);
		_elevationSpacer = new BSpacer(192, 120, Policy_Fixed, Policy_Fixed);

		_showAreaCheckBox = new BCheckBox("Show Area");
		_showPointsCheckBox = new BCheckBox("Show Points");
		_showTerrainCheckBox = new BCheckBox("Show Terrain");
		_swapYZCheckBox = new BCheckBox("Swap YZ");
		_optimizedCheckBox = new BCheckBox("Optimized");
		_optimizedCheckBox->setEnabled(false);

		BLabel* widthLabel = new BLabel("width");
		_widthSpinBox = new BRealSpinBox(0, BReal(999999999));
		_widthSpinBox->setFormulable(true);

		BLabel* heightLabel = new BLabel("height");
		_heightSpinBox = new BRealSpinBox(0, BReal(999999999));
		_heightSpinBox->setFormulable(true);

		BLabel* styleLabel = new BLabel("Style");
		_stateComboBox = new BComboBox();
		_stateComboBox->addItem("Poly_Point", Poly_Point);
		_stateComboBox->addItem("Poly_Line", Poly_Line);
		_stateComboBox->addItem("Poly_Fill", Poly_Fill);
		_stateComboBox->setValue(Poly_Fill);

		BGridLayout* gridLayout = new BGridLayout();
		gridLayout->setWidget(0, 0, widthLabel);
		gridLayout->setWidget(0, 1, _widthSpinBox);
		gridLayout->setWidget(1, 0, heightLabel);
		gridLayout->setWidget(1, 1, _heightSpinBox);
		gridLayout->setWidget(2, 0, styleLabel);
		gridLayout->setWidget(2, 1, _stateComboBox);

		rightLayout->addWidget(imageLabel);
		rightLayout->addSpacer(_imageSpacer);
		rightLayout->addSpring(1);
		rightLayout->addWidget(elevationLabel);
		rightLayout->addSpacer(_elevationSpacer);
		rightLayout->addWidget(_showAreaCheckBox);
		rightLayout->addWidget(_showPointsCheckBox);
		rightLayout->addWidget(_showTerrainCheckBox);
		rightLayout->addWidget(_swapYZCheckBox);
		rightLayout->addWidget(_optimizedCheckBox);
		rightLayout->addLayout(gridLayout);
		rightLayout->addSpring(100);
	}

	BVBoxLayout* vlayout = new BVBoxLayout();
	{
		_openButton = new BButton("Open");
		_resetButton = new BButton("Reset");
		_orthoButton = new BButton("Ortho");
		_orthoButton->setCheckable(true);
		_extractButton = new BButton("Extract");
		_extractButton->setEnabled(false);
		_extractButton->setCheckable(true);
		_progressBar = new BProgressBar();

		BHBoxLayout* buttonLayout = new BHBoxLayout();
		buttonLayout->addWidget(_openButton);
		buttonLayout->addWidget(_resetButton);
		buttonLayout->addWidget(_orthoButton);
		buttonLayout->addWidget(_extractButton);
		buttonLayout->addWidget(_progressBar, 1000);

		vlayout->addWidget(_viewer, 100);
		vlayout->addLayout(buttonLayout);
	}

	BHBoxLayout* hlayout = new BHBoxLayout(this);
	hlayout->addLayout(vlayout);
	hlayout->addLayout(rightLayout);

	connect(_showAreaCheckBox, Signal_Checked, &ConvertDialog::slotShowAreaClicked);
	connect(_showPointsCheckBox, Signal_Checked, &ConvertDialog::slotShowPointsClicked);
	connect(_showTerrainCheckBox, Signal_Checked, &ConvertDialog::slotShowTerrainClicked);
	connect(_swapYZCheckBox, Signal_Clicked, &ConvertDialog::slotSwapYZClicked);
	connect(_optimizedCheckBox, Signal_Clicked, &ConvertDialog::slotOptimizedClicked);

	connect(_stateComboBox, Signal_CurrentChanged, &ConvertDialog::slotStateChanged);
	connect(_widthSpinBox, Signal_EditFinished, &ConvertDialog::slotSizeEdited);
	connect(_heightSpinBox, Signal_EditFinished, &ConvertDialog::slotSizeEdited);

	connect(_openButton, Signal_Clicked, &ConvertDialog::slotOpenButtonClicked);
	connect(_resetButton, Signal_Clicked, &ConvertDialog::slotResetButtonClicked);
	connect(_orthoButton, Signal_Clicked, &ConvertDialog::slotOrthoButtonClicked);
	connect(_extractButton, Signal_Clicked, &ConvertDialog::slotExtractButtonClicked);
	connect(_orthoCamera, Signal_Frame, &ConvertDialog::slotOrthoCameraFrame);
	connect(_handler, "area-adjusted", &ConvertDialog::slotAreaAdjusted);

	_stateComboBox->setEnabled(false);
	_widthSpinBox->setEnabled(false);
	_heightSpinBox->setEnabled(false);
	_showAreaCheckBox->setChecked(true);
	_showTerrainCheckBox->setChecked(true);

	setSampleSize(BSize(320, 200));
}
ConvertDialog::~ConvertDialog()
{

}

void ConvertDialog::setSampleSize(const BSize& sampleSize)
{
	if (_sampleSize != sampleSize)
	{
		_sampleSize = sampleSize;
		int count = _sampleSize.width() * _sampleSize.height();
		BVectorArray* vertices = new BVectorArray(count);
		_pointsGeometry->setVertices(vertices);

		_elevationImage->setSize(sampleSize);

		double ratio = (double)sampleSize.height() / sampleSize.width();
		_imageSpacer->setSize(100, int(100 * ratio));
		_elevationSpacer->setSize(100, int(100 * ratio));
		_orthoCamera->setPixelSize(1920, int(1920 * ratio));
		_orthoImage->setSize(1920, int(1920 * ratio));
	}
}
const BSize& ConvertDialog::sampleSize() const
{
	return _sampleSize;
}

const BSpace& ConvertDialog::space() const
{
	return _orthoArea;
}
BImage* ConvertDialog::image() const
{
	return _orthoImage;
}

void ConvertDialog::createScene()
{
	_scene = new BScene;
	_scene->setName("convert scene");

	_light = new BLight(BLight::Type_Direct);
	_light->setPosition(1.0f, 0.0f, 1.0f);
	_scene->insert(_light);

	_pointsGeometry = new BGeometry();
	{
		_pointsGeometry->setLighting(false);
		_pointsGeometry->setPointSmooth(true);
		_pointsGeometry->setPointSize(3);

		BVectorArray* vertices = new BVectorArray();
		_pointsGeometry->setVertices(vertices);
		_pointsGeometry->setColor(255, 0, 0);
		_pointsGeometry->addElement(Primitive_Points, 0, 0);
	}
	_scene->insert(_pointsGeometry);
	_pointsGeometry->setVisible(false);

	_orthoCamera = new BCamera();
	_orthoCamera->setOrtho(true);
	_scene->insert(_orthoCamera);

}
void ConvertDialog::updateScene()
{
	const BSpace& space = _node->space();
	BReal near = space.radius() * BReal(0.01);
	BReal far = space.radius() * BReal(10);
	_camera->setLensWidth(near);
	_camera->setNear(near);
	_camera->setFar(far);
	_camera->setPosition(space.max() + BVector(0, 0, space.depth()));
	_camera->setCenter(space.center());

	_light->setPosition(space.max() + BVector(space.radius(), space.radius(), space.radius()));

	BReal hw = space.width() * 0.5f;
	BReal hh = space.width() / _sampleSize.width() * _sampleSize.height() * 0.5f;

	BVector center = space.center();
	_orthoArea = space;
	_orthoArea.min().x() = center.x() - hw;
	_orthoArea.max().x() = center.x() + hw;
	_orthoArea.min().y() = center.y() - hh;
	_orthoArea.max().y() = center.y() + hh;

	_handler->setArea(_orthoArea);

	_orthoCamera->setPosition(BVector(_orthoArea.center().x(), _orthoArea.center().y(), _orthoArea.max().z()));
	_orthoCamera->setCenter(_orthoArea.center());
	_orthoCamera->setUp(BVector(0, 1, 0));

	_orthoCamera->setLensWidth(_orthoArea.width());
	_orthoCamera->setLensHeight(_orthoArea.height());
	_orthoCamera->setNear(-_orthoArea.radius() * BReal(0.1));
	_orthoCamera->setFar(_orthoArea.radius() * BReal(10));

	slotOrthoButtonClicked();
	this->fresh();
}

void ConvertDialog::slotShowAreaClicked()
{
	bool visible = _showAreaCheckBox->checked();
	if (visible)
	{
		_handler->showArea();
	}
	else
	{
		_handler->hideArea();
	}
}
void ConvertDialog::slotShowPointsClicked()
{
	bool visible = _showPointsCheckBox->checked();
	_pointsGeometry->setVisible(visible);
}
void ConvertDialog::slotShowTerrainClicked()
{
	bool visible = _showTerrainCheckBox->checked();
	if (_node)
		_node->setVisible(visible);
}
void ConvertDialog::slotSwapYZClicked()
{
	if (_node == 0)
		return;
	if (_swapYZCheckBox->checked())
	{
		for (int i = 0; i < _node->shapeCount(); i++)
		{
			BShape* shape = _node->shape(i);
			if (BMesh* mesh = dynamic_cast<BMesh*>(shape))
			{
				BVectorArray* vertices = mesh->vertices();
				for (int vi = 0; vi < vertices->size(); vi++)
				{
					BVector& v = (*vertices)[vi];
					v.z() = -v.z();
					bSwap(v.y(), v.z());
				}
			}
			if (BGeometry* geometry = dynamic_cast<BGeometry*>(shape))
			{
				BVectorArray* vertices = geometry->vertices();
				for (int vi = 0; vi < vertices->size(); vi++)
				{
					BVector& v = (*vertices)[vi];
					v.z() = -v.z();
					bSwap(v.y(), v.z());
				}
			}
			shape->dirty();
		}
	}
	else
	{
		for (int i = 0; i < _node->shapeCount(); i++)
		{
			BShape* shape = _node->shape(i);
			if (BMesh* mesh = dynamic_cast<BMesh*>(shape))
			{
				BVectorArray* vertices = mesh->vertices();
				for (int vi = 0; vi < vertices->size(); vi++)
				{
					BVector& v = (*vertices)[vi];
					bSwap(v.y(), v.z());
					v.z() = -v.z();
				}
			}
			if (BGeometry* geometry = dynamic_cast<BGeometry*>(shape))
			{
				BVectorArray* vertices = geometry->vertices();
				for (int vi = 0; vi < vertices->size(); vi++)
				{
					BVector& v = (*vertices)[vi];
					bSwap(v.y(), v.z());
					v.z() = -v.z();
				}
			}
			shape->dirty();
		}
	}
	updateScene();
}
void ConvertDialog::slotOptimizedClicked()
{
	bool optimized = _optimizedCheckBox->checked();
	for (int i = 0; i < _node->shapeCount(); i++)
	{
		BShape* shape = _node->shape(i);
		if (BMesh* mesh = dynamic_cast<BMesh*>(shape))
			mesh->setOptimized(optimized);
		else if (BGeometry* geometry = dynamic_cast<BGeometry*>(shape))
			geometry->setOptimized(optimized);
		else if (BTerrain* terrain = dynamic_cast<BTerrain*>(shape))
			terrain->setOptimized(optimized);
	}
}

void ConvertDialog::slotStateChanged()
{
	PolyMode polyMode = _stateComboBox->value();
	for (int i = 0; i < _node->shapeCount(); i++)
	{
		BShape* shape = _node->shape(i);
		shape->setPolyMode(polyMode);
	}
}
void ConvertDialog::slotSizeEdited()
{
	BReal width = _widthSpinBox->value();
	BReal height = _heightSpinBox->value();

	for (int i = 0; i < _node->shapeCount(); i++)
	{
		BShape* shape = _node->shape(i);
		BTerrain* terrain = dynamic_cast<BTerrain*>(shape);
		if (terrain)
		{
			terrain->setWidth(width);
			terrain->setHeight(height);
		}
	}

	updateScene();
}
void ConvertDialog::slotAreaAdjusted()
{
	_orthoArea = _handler->area();

	_orthoCamera->setPosition(BVector(_orthoArea.center().x(), _orthoArea.center().y(), _orthoArea.max().z()));
	_orthoCamera->setCenter(_orthoArea.center());
	_orthoCamera->setUp(BVector(0, 1, 0));

	_orthoCamera->setLensWidth(_orthoArea.width());
	_orthoCamera->setLensHeight(_orthoArea.height());
	_orthoCamera->setNear(-_orthoArea.radius() * BReal(0.1));
	_orthoCamera->setFar(_orthoArea.radius() * BReal(10));
}

void ConvertDialog::slotOpenButtonClicked()
{
	_extractButton->setEnabled(false);
	BString fileName = BFileDialog::OpenFile(this, "Load model file", "", "*.elv;*.tif;*.3ds");
	if (fileName.empty())
		return;
	BNode* node = 0;
	if (BTerrain* terrain = CreateTerrain(fileName))
	{
		node = new BNode();
		node->addShape(terrain);
		_widthSpinBox->setValue(terrain->width());
		_heightSpinBox->setValue(terrain->height());
		_widthSpinBox->setEnabled(true);
		_heightSpinBox->setEnabled(true);
		_stateComboBox->setEnabled(true);
	}
	else
	{
		node = ReadFile<BNode>(fileName);
		_widthSpinBox->setEnabled(false);
		_heightSpinBox->setEnabled(false);
		_stateComboBox->setEnabled(true);
		_swapYZCheckBox->setChecked(false);
	}
	if (_node)
	{
		_scene->remove(_node);
		_node = 0;
	}
	_node = node;
	if (_node)
	{
		slotOptimizedClicked();
		slotShowTerrainClicked();
		_scene->insert(_node);
		updateScene();
	}
	_handler->setNode(_node);
	_showAreaCheckBox->setEnabled(_node);
	_showPointsCheckBox->setEnabled(_node);
	_showTerrainCheckBox->setEnabled(_node);
	_swapYZCheckBox->setEnabled(_node);
	_optimizedCheckBox->setEnabled(_node);
	_extractButton->setEnabled(_node);
}
void ConvertDialog::slotResetButtonClicked()
{
	if (_node)
	{
		_scene->remove(_node);
		_node = 0;
		_handler->setNode(0);
		_showAreaCheckBox->setEnabled(false);
		_showPointsCheckBox->setEnabled(false);
		_showTerrainCheckBox->setEnabled(false);
		_swapYZCheckBox->setEnabled(false);
		_optimizedCheckBox->setEnabled(false);
		_extractButton->setEnabled(false);
	}
}
void ConvertDialog::slotOrthoButtonClicked()
{
	if (!_node)
		return;
	if (_orthoButton->checked())
	{
		BSize viewSize = _viewer->size();

		BSpace space = _node->space();
		BReal width = space.width();
		BReal height = width * viewSize.height() / viewSize.width();
		if (height < space.height())
		{
			height = space.height();
			width = height * viewSize.width() / viewSize.height();
		}

		_camera->setOrtho(true);
		_camera->setPosition(space.center() + BVector(0, 0, space.depth() * 5));
		_camera->setCenter(space.center());
		_camera->setUp(BVector(0, 1, 0));
		_camera->setLensWidth(width);
		_camera->setLensHeight(height);
		_camera->setNear(0);
		_camera->setFar(space.radius() * 10);

		_viewer->fresh();
		_viewer->setHandler(_handler);
		//_adjustHandler->home();
	}
	else
	{
		const BSpace& space = _node->space();
		_camera->setOrtho(false);
		_camera->setFovy(36);
		_camera->setNear(space.radius() * 0.01f);
		_camera->setFar(space.radius() * 10.0f);

		_camera->setPosition(space.max());
		_camera->setCenter(space.center());
		_camera->setUp(0, 0, 1);

		_viewer->setHandler(_handler);
		//_sphereHandler->home();
	}
}
void ConvertDialog::slotExtractButtonClicked()
{
	_elevation.resize(_sampleSize.height(), _sampleSize.width());
	_elevation.fill(0.0f);

	_counter.resize(_sampleSize.height(), _sampleSize.width());
	_counter.fill(0);

	BSpace space = _orthoArea;
	BReal ex = space.width() / _elevation.column() / 2.0f;
	BReal ey = space.height() / _elevation.row() / 2.0f;
	space.min().x() -= ex;
	space.min().y() -= ey;
	space.max().x() += ex;
	space.max().y() += ey;
	for (int i = 0; i < _node->shapeCount(); i++)
	{
		BShape* shape = _node->shape(i);
		const BVectorArray* vertices = 0;
		if (BMesh* mesh = dynamic_cast<BMesh*>(shape))
			vertices = mesh->vertices();
		else if (BGeometry* geometry = dynamic_cast<BGeometry*>(shape))
			vertices = geometry->vertices();
		if (vertices)
		{
			for (int vi = 0; vi < vertices->size(); vi++)
			{
				const BVector& v = (*vertices)[vi];
				int col = int((v.x() - space.min().x()) / space.width() * _elevation.column());
				int row = int((v.y() - space.min().y()) / space.height() * _elevation.row());
				_elevation(row, col) += v.z();
				_counter(row, col)++;
			}
		}
	}
	_scanRow = 0;
	_progressBar->setValue(0);

	_handler->lostLines().reset();

}

void ConvertDialog::slotOrthoCameraFrame(BObject* object, const BValue& value)
{
	_orthoCamera->capture(_orthoImage);
	this->fresh();
}

void ConvertDialog::updateEvent(const BEvent& event)
{
	if (_extractButton->checked())
	{
		BSpace area = _orthoArea;
		int sampleCount = _sampleSize.width() * _sampleSize.height();
		int width = _sampleSize.width();
		int height = _sampleSize.height();

		BPicker picker;
		if (_scanRow < height)
		{
			BLineArray& lostLines = _handler->lostLines();
			int head = _scanRow * width;
			BReal y = (_scanRow + 0.5f) / height * area.height() + area.min().y();
			for (int c = 0; c < width; c++)
			{
				int index = head + c;
				if (_counter.data()[index] > 0)
				{
					_elevation.data()[index] /= _counter.data()[index];
				}
				else
				{
					BReal x = (c + 0.5f) / width * area.width() + area.min().x();
					BLine line(x, y, area.max().z() + area.depth(), x, y, area.min().z() - area.depth());
					picker.setLine(line);
					const BPickItem* item = picker.apply(_node);
					if (item)
					{
						_elevation.data()[index] = item->absolutePoint().z();
					}
					else
					{
						lostLines.append(line);
					}
				}
			}
			BVectorArray* vertices = _pointsGeometry->vertices();
			if (vertices && vertices->size() == _elevation.size())
			{
				BReal uz = area.depth() * 0.05f;
				BReal sx = area.width() / _elevation.column();
				BReal sy = area.height() / _elevation.row();
				for (auto it = _elevation.begin(); it.valid(); ++it)
				{
					BReal x = it.column() * sx + area.min().x();
					BReal y = it.row() * sy + area.min().y();
					(*vertices)[it.index()].set(x, y, *it + uz);
				}
				_pointsGeometry->setVertices(vertices);
				_pointsGeometry->element(0)->setCount(sampleCount);
			}
			//update elevation image.
			BByteArray* pixels = _elevationImage->pixels();
			if (pixels && pixels->size() == _elevation.size())
			{
				BReal depth = area.depth();
				BReal mult = 1.0f / depth * 255;
				for (auto it = _elevation.begin(); it.valid(); ++it)
				{
					(*pixels)[it.index()] = (BByte)((*it - area.min().z()) * mult);
				}
				_elevationImage->dirty();
			}
			_scanRow++;
			_progressBar->setMaximum(height);
			_progressBar->setValue(_scanRow);
		}
		else
		{
			emit("apply");
			_extractButton->setChecked(false);
			_progressBar->setValue(0);
		}
		_viewer->fresh();
		this->fresh();
	}
}
void ConvertDialog::resizeEvent(const BEvent& event)
{
	BDialog::resizeEvent(event);
}
void ConvertDialog::paintEvent(const BEvent& event)
{
	BDialog::paintEvent(event);

	BPainter painter(this);

	painter.bind(_orthoCamera);
	//painter.bind(_orthoImage);
	painter.fillRect(_imageSpacer->rect());
	painter.unbind();

	painter.bind(_elevationImage);
	painter.fillRect(_elevationSpacer->rect());
	painter.unbind();

	painter.setColor(0, 255, 0);
	{
		BRect imageRect = _imageSpacer->rect();
		imageRect.left() -= 2;
		imageRect.top() -= 1;
		imageRect.right() += 1;
		imageRect.bottom() += 2;
		painter.drawRect(imageRect);

		BRect elevaRect = _elevationSpacer->rect();
		elevaRect.left() -= 2;
		elevaRect.top() -= 1;
		elevaRect.right() += 1;
		elevaRect.bottom() += 2;
		painter.drawRect(elevaRect);
	}
}
